/*
     BinaryStream.h
	 This file contains a C++ implementation of the System.IO.BinaryReader and System.IO.BinaryWriter. (They do not contain all the functions of the .NET classes tho)

	 Date Created: 7/27/2013
	 Initial Author: Elio Decolli
	 Web Site: ecoders.weebly.com

	 Copyright (C) eCoders 2013.
*/

#include <Windows.h>
#include <iostream>

template <typename T>
	T BytesToType(int len, BYTE* bytes)
{
	int len = sizeof(bytes) / sizeof(BYTE);
	BYTE bts[len] = malloc(len);

	T type = 0;
	for(int i = len; i >= 0; i--)
	{
		type = (type << 8) + bts[i];
	}
	return type;
}

class BinaryReader
{
private:
	LPVOID		_stream;
	int position;
	int len;
public:
	BinaryReader(void	*stream)
	{
		memcpy(_stream, stream, sizeof(stream));
		position = 0;
	    len = sizeof(stream) / sizeof(BYTE);
	}

	inline __int32 ReadInt32()
	{
		int k = sizeof(__int32);
		if(len - position < k)
			return NULL;
		BYTE data[4];
		for(int i = 0; i < 4; i++)
		{
			data[i] = ((BYTE*)_stream)[i];
			position++;
		}
		__int32 r = BytesToType<__int32>(4, data);
		//Help the GC?
		delete[] data;
		delete &k;
		//Return
		return r;
	}

	inline __int64 ReadInt64()
	{
		int k = sizeof(__int64);
		if(len - position < k)
			return NULL;
		BYTE data[8];
		for(int i = 0; i < 8; i++)
		{
			data[i] = ((BYTE*)_stream)[i];
			position++;
		}
		__int64 r = BytesToType<__int64>(8, data);
		//Help the GC?
		delete[] data;
		delete &k;
		//Return
		return r;
	}

	inline const char* ReadString(int length)
	{
		if(len - position < length)
			return NULL;
		BYTE *data;
		for(int i = 0; i < length; i++)
		{
			data[i] = ((BYTE*)_stream)[i];
			position++;
		}
		std::string kk(reinterpret_cast<char*>((unsigned char*)data));
		const char *r = kk.c_str();
		delete[] data;
		delete &kk;
		return r;
	}
};


class BinaryWriter
{
private:
	LPVOID		_stream;
	int			_len;
public:
	BinaryWriter(LPVOID stream)
	{
		_stream = stream;
		_len = sizeof((BYTE*)_stream) / sizeof(BYTE);
	}

	template<typename T>
	VOID Write(LPVOID data)
	{
		LPVOID tempStream;
		memcpy(tempStream, data, sizeof(T));
		_stream += tempStream;
	}
};